//
//  KLineSQLite.cpp
//  Chart
//
//  Created by CaoJun on 13-11-6.
//
//

#include "KLineSQLite.h"
#include "YTXChartTools.h"

using namespace ytx;
using namespace std;

KLineSQLite::KLineSQLite() : BaseSQLite(){
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = paths[0];
    NSString *fileName = [NSString stringWithFormat:@"%@/KLineData.rdb", documentsDirectory];
    path = [fileName UTF8String];
}

KLineSQLite::~KLineSQLite(){
    sqlite3_close(sqliteDB);
}

bool KLineSQLite::checkInRange(string tableName, YTXTime * outputLastTime, KLineData * kData, YTXTime tradeDate)
{
    if(openDB())
    {
        DBResult dbResult;
        dbResult.status = false;
        char * errmsg = 0;
        const string queryStr = "SELECT date FROM "+ tableName+" ORDER BY date DESC LIMIT 0,1";
        int ret = sqlite3_exec(sqliteDB, queryStr.c_str(), BaseSQLite::handelr_exec, &dbResult, &errmsg);
        CheckResult(ret, errmsg);
        CheckDBResult(dbResult, "checkInRange");
        string tempTime = dbResult.getValue(0,0);
        
        long latestValue = Tools::parseLong(tempTime);
        
        YTXTime lastestTime = YTXTime(latestValue);
        
        (*outputLastTime) = lastestTime;

//        NSLog(@"KLineSQLite.checkInRange lastestTime:%@", [NSString stringWithUTF8String:lastestTime.toStringYYYYMMddHHmmss().c_str()] );
//        NSLog(@"KLineSQLite.checkInRange tradeDate:%@", [NSString stringWithUTF8String: tradeDate.toStringYYYYMMddHHmmss().c_str() ]);
        
        sqlite3_close(sqliteDB);
        return kData->isInLatestNewK(lastestTime, tradeDate);
        
    }
    sqlite3_close(sqliteDB);
    return false;
}

bool KLineSQLite::getDataFromDB(string tableName,YTXTime time, vector<KLineItem> * kLineItems, const unsigned int count)
{
    if(openDB())
    {
        DBResult dbResult;
        dbResult.status = false;
        char * errmsg = 0;
        const string queryStr = "SELECT * FROM "+ tableName+" WHERE date<"+ ConvertToString( time.getCurrentTime() ) +" ORDER BY date DESC LIMIT 0,"+ ConvertToString(count);
        int ret = sqlite3_exec(sqliteDB, queryStr.c_str(), BaseSQLite::handelr_exec, &dbResult, &errmsg);
        CheckResult(ret, errmsg);
        CheckDBResult(dbResult, "getDataFromDB");
        (*kLineItems) = transforDataKLineItem(dbResult);
        sqlite3_close(sqliteDB);
        return true;
        
    }
    sqlite3_close(sqliteDB);
    return false;
}

vector<KLineItem> KLineSQLite::transforDataKLineItem(DBResult & dbResult)
{
    vector<KLineItem> result;
    string tradeDate;
    YTXTime date;
    double open,close,high,low,volume,value,hold,change, percent;
    unsigned int index = 0;
    unsigned int size = (unsigned int)(dbResult.row_value.size() - 1);
    //有多少列是确定的
    for (vector<vector <string> >::reverse_iterator it =  dbResult.row_value.rbegin(); it != dbResult.row_value.rend(); ++it) {
        index = size - (unsigned int)(it-dbResult.row_value.rbegin());
        date = YTXTime( Tools::parseLong( dbResult.getValue(index, 0) ) );
        open = Tools::parseDouble( dbResult.getValue(index, 1) );
        high = Tools::parseDouble( dbResult.getValue(index, 2) );
        low = Tools::parseDouble( dbResult.getValue(index, 3) );
        close = Tools::parseDouble( dbResult.getValue(index, 4) );
        
        volume = Tools::parseDouble( dbResult.getValue(index, 5) );
        value = Tools::parseDouble( dbResult.getValue(index, 6) );
        hold = Tools::parseDouble( dbResult.getValue(index, 7) );
        change = Tools::parseDouble( dbResult.getValue(index, 8) );
        percent = Tools::parseDouble( dbResult.getValue(index, 9) );
        tradeDate = dbResult.getValue(index, 10);
        KLineItem ochl = {
            tradeDate,
            open,
            high,
            low,
            close,
            volume,
            value,
            hold,
            date,
            change,
            percent
        };
        
        result.push_back(ochl);
    }
    
    return result;
}


bool KLineSQLite::insertData(string tableName, vector<KLineItem> dataList)
{
    if (openDB())
    {
        char * errmsg = 0;
        sqlite3_exec(sqliteDB, "begin;", 0, 0, 0);

        for (vector<KLineItem>::iterator iter = dataList.begin() ; iter != dataList.end() ; iter++ )
        {
            KLineItem data = (*iter);
            const string sqlStr = "INSERT INTO "+ tableName +" (date, open, high, low, close, volume, value, hold, change, percent, tradeDate) VALUES("+ ConvertToString(data.dateTime.getCurrentTime()) + "," + ConvertToString(data.open)+","+ ConvertToString(data.high)+","+ ConvertToString(data.low)+","+ ConvertToString(data.close)+","+ ConvertToString(data.volume)+","+ ConvertToString(data.value)+","+ ConvertToString(data.totalHold)+","+ ConvertToString(data.upDrop)+","+ ConvertToString(data.percent) + "," + data.tradeDate +")";
            int ret = sqlite3_exec(sqliteDB, sqlStr.c_str(), 0, 0, &errmsg);
            ContinueResult(ret, errmsg);
        }
        sqlite3_exec(sqliteDB, "commit;", 0, 0, 0);
        sqlite3_close(sqliteDB);
        return true;
    }
    return false;
}

bool KLineSQLite::createKLineDataTableIfNotExit(const string tableName){
    //    sqlite3_stmt *stmt = NULL;
//    sqlite3 * sqliteDB = getDB(path, false);
    if (openDB()){
        char * errmsg = 0;
        int ret;
        const string hasTbaleSQL = "SELECT COUNT(*) FROM sqlite_master where type='table' AND name='"+tableName+"'";

        DBResult dbResult;
        dbResult.status = false;

        ret = sqlite3_exec(sqliteDB,hasTbaleSQL.c_str(), BaseSQLite::handelr_exec, &dbResult, &errmsg);

        CheckResult(ret, errmsg);

        if (Tools::parseInt(dbResult.getValue(0, 0)) > 0) {
//            sqlite3_close(sqliteDB);
            return true;
        }

        const string createTableSQL =
            "CREATE TABLE "+ tableName +" (\
            date INTEGER PRIMARY KEY NOT NULL UNIQUE,\
            open REAL,\
            high REAL,\
            low REAL,\
            close REAL,\
            volume REAL DEFAULT 0.0,\
            value REAL DEFAULT 0.0,\
            hold REAL DEFAULT 0.0,\
            change REAL,\
            percent REAL,\
            tradeDate TEXT\
        )";

        ret = sqlite3_exec(sqliteDB,createTableSQL.c_str(), handelr_exec, &dbResult, &errmsg);

        CheckResult(ret, errmsg);

//        sqlite3_close(sqliteDB);
        return true;
    }

    sqlite3_close(sqliteDB);
    return false;
}

bool KLineSQLite::vacuumDB()
{
    if (openDB())
    {
        char * errmsg = 0;
        int ret;
        const string hasTbaleSQL = "VACUUM";
        
        DBResult dbResult;
        dbResult.status = false;
        
        ret = sqlite3_exec(sqliteDB,hasTbaleSQL.c_str(), BaseSQLite::handelr_exec, &dbResult, &errmsg);
        
        CheckResult(ret, errmsg);
        return true;
    }
    sqlite3_close(sqliteDB);
    return false;
}
